﻿/**
 *
 * battery.c
 *
 *  Created on: 2019-12-03
 *      Author: chenshisheng
 */

#include "battery.h"
#include "adc.h"
#include "power_manager.h"
#include "utils.h"

#define ADCx ADC1
#define AVERAGE_NUM 4

// ADC的参考电压（mV）
#define REF_VOLRAGE 3300

#define Rh 200000

#define R_SAMPLE 23000

static const struct
{
    int voltage;
    int percent;
} _VolPerTable[] =
{
        {13200, 100},
        {12900, 85},
        {12500, 70},
        {12000, 50},
        {11500, 25},
        {11000, 0},
};

void Battery_Init(void)
{
    MX_ADC_Init();
}

static int _VoltageToPercent(int voltage)
{
    unsigned int i, size;
    int per = 0;

    size = ARRAY_SIZE(_VolPerTable);
    if(voltage >= _VolPerTable[0].voltage)
    {
        return _VolPerTable[0].percent;
    }

    if(voltage <= _VolPerTable[size - 1].voltage)
    {
        return _VolPerTable[size - 1].percent;
    }

    for(i = 0; i < size; i++)
    {
        if(voltage == _VolPerTable[i].voltage)
        {
            per = _VolPerTable[i].percent;
            break;
        }

        if(voltage > _VolPerTable[i].voltage)
        {
            per = Utils_InterpolateInt(
                    _VolPerTable[i - 1].voltage,
                    _VolPerTable[i - 1].percent,
                    _VolPerTable[i].voltage,
                    _VolPerTable[i].percent,
                    voltage);
            break;
        }
    }

    return per;
}

int Battery_VoltageMeasure(int *voltage, int *percent)
{
    int adc, adcVoltage, batVoltage;
    int i, ret;

    LL_ADC_REG_StartConversion(ADCx);
    adc = 0;
    for(i = 0; i < AVERAGE_NUM; i++)
    {
        while (LL_ADC_IsActiveFlag_EOC(ADC1) == 0)
        {
        }

        adc += LL_ADC_REG_ReadConversionData12(ADCx);
    }

    adc /= AVERAGE_NUM;
    adcVoltage = __LL_ADC_CALC_DATA_TO_VOLTAGE(REF_VOLRAGE, adc, LL_ADC_RESOLUTION_12B);
    batVoltage = adcVoltage * (Rh + R_SAMPLE) / R_SAMPLE;
    if(voltage)
    {
        *voltage = batVoltage;
    }

    if(percent)
    {
        i = _VoltageToPercent(batVoltage);
        if(i < 0)
        {
            i = 0;
        }
        else if(i > 100)
        {
            i = 100;
        }

        *percent = i;
    }

    if(batVoltage < (_VolPerTable[ARRAY_SIZE(_VolPerTable) - 1].voltage - 500))
    {
        ret = -1;
    }
    else
    {
        ret = 0;
    }

    return ret;
}

int Battery_MeasureCmd(Stream_t *stream, int argc, char *argv[])
{
    int ret, v, p;

    ret = Battery_VoltageMeasure(& v, & p);
    chprintf(stream, "Battery: %dmV, %d%%, %s\n", v, p, (ret == 0) ? "OK" : "ERROR");

    return 0;
}
